// Data Field

#include <qua/field.h>
#include <qua/fixed.h>
#include <qua/text.h>
#include <qua/time.h>
#include <qua/error.h>
#include <qua/cast.h>
#include <qua/opt.h>
#include <utility>

namespace qua
{
    class field::data
    {
    public:
        data( field::format const& fmt )
            : m_format( fmt ) {
        }

        virtual ~data() {
        }

        field::format const& get_format() const {
            return m_format;
        }

        const wchar_t* get_name() const {
            return m_format.get_name();
        }

        field::type get_type() const {
            return m_format.get_type();
        }

        virtual bool is_null() = 0;

        virtual void clear() = 0;

        virtual size_t size() = 0;

        template< field::type T >
        struct of;

    private:
        field::format const& m_format;
    };

    template< typename T >
    class field::value : public field::data
    {
    public:
        typedef field::data base;

        value( field::format const& fmt )
            : base( fmt ), m_value()
        {
            if( !fmt.is_null_default() )
                m_value = fmt.get_default<T>();
        }

        value( field::format const& fmt, T val )
            : base( fmt ), m_value( val ) {
        }

        value( field::format const& fmt, std::nullptr_t )
            : base( fmt ), m_value() {
        }

        virtual bool is_null() override {
            return !m_value;
        }

        virtual void clear() override {
            m_value = opt<T>();
        }

        virtual size_t size() override {
            return sizeof( *this );
        }

        void set_value( T val ) {
            m_value = val;
        }

        void assert_value_is_not_null() const
        {
            if( !m_value )
                throw error( "Trying to retrieve value from NULL in field \"" + text( get_format().get_name() ) + '"', __FILE__, __LINE__ );
        }

        T get_value() const
        {
            assert_value_is_not_null();
            return *m_value;
        }

        T const& get_value_ref() const
        {
            assert_value_is_not_null();
            return *m_value;
        }

        T& get_value_ref()
        {
            assert_value_is_not_null();
            return *m_value;
        }

    private:
        opt<T> m_value;
    };

    template< field::type T >
    struct field::data::of
    {
        typedef field::value< typename field::type_of<T>::type > type;
    };

    text field::type_text( field::type t )
    {
        static const char* TYPE_NAME[] = {
            "boolean",
            "integer",
            "float",
            "text",
            "time",
            "unknown type"
        };
        if( t < 0 || t > field::of_unknown_type )
            t = field::of_unknown_type;
        return text( TYPE_NAME[ t ] );
    }

    void invalid_field_type( field::format const& fmt )
    {
        throw error( "Unsupported type (" + text( field::type_text( fmt.get_type() ) ) + ") of field \"" + text( fmt.get_name() ) + '"', __FILE__, __LINE__ );
    }

    field::field( void* at, field::format const& fmt )
    {
        switch( fmt.get_type() )
        {
        case of_bool:
            m_data = new(at) field::data::of< of_bool >::type( fmt );
            break;
        case of_int:
            m_data = new(at) field::data::of< of_int >::type( fmt );
            break;
        case of_float:
            m_data = new(at) field::data::of< of_float >::type( fmt );
            break;
        case of_fixed:
            m_data = new(at) field::data::of< of_fixed >::type( fmt );
            break;
        case of_text:
            m_data = new(at) field::data::of< of_text >::type( fmt );
            break;
        case of_time:
            m_data = new(at) field::data::of< of_time >::type( fmt );
            break;
        default:
            invalid_field_type( fmt );
            break;
        }
    }

    field::~field()
    {
        switch( get_type() )
        {
        case of_bool:
            static_cast< field::data::of< of_bool >::type* >( m_data )->~value();
            break;
        case of_int:
            static_cast< field::data::of< of_int >::type* >( m_data )->~value();
            break;
        case of_float:
            static_cast< field::data::of< of_float >::type* >( m_data )->~value();
            break;
        case of_fixed:
            static_cast< field::data::of< of_fixed >::type* >( m_data )->~value();
            break;
        case of_text:
            static_cast< field::data::of< of_text >::type* >( m_data )->~value();
            break;
        case of_time:
            static_cast< field::data::of< of_time >::type* >( m_data )->~value();
            break;
        default:
            break;
        }
    }

    field::type field::get_type() const
    {
        return m_data->get_type();
    }

    text field::get_name() const
    {
        return m_data->get_name();
    }

    field::format const& field::get_format() const
    {
        return m_data->get_format();
    }

    template< typename T >
    T invalid_field_type_ret( field::format const& fmt )
    {
        invalid_field_type( fmt );
        return T();
    }

    bool field::is_null() const
    {
        return m_data->is_null();
    }

    void field::clear()
    {
        m_data->clear();
    }

    size_t field::data_size() const
    {
        return m_data->size();
    }

    text field::to_text() const
    {
        switch( get_type() )
        {
        case of_text:
            return static_cast< field::data::of< of_text >::type* >( m_data )->get_value();
        case of_bool:
            return cast<text>( static_cast< field::data::of< of_bool >::type* >( m_data )->get_value() );
        default:
            return invalid_field_type_ret<const wchar_t*>( get_format() );
        }
    }

    template< field::type T >
    typename field::type_of<T>::type unsupported_value_type( field::type t, text const& field_name )
    {
        throw error( "Unsupported value type " + field::type_text(T) + " for field type '" + field::type_text(t) + "' of field \"" + field_name + '"', __FILE__, __LINE__ );
    }

    template<>
    field::field( void* at, field::format const& format, field::type_of< field::of_bool >::type value )
    {
        switch( format.get_type() )
        {
        case of_bool:
            m_data = new(at) data::of< of_bool  >::type( format, value );
            break;
        case of_int:
            m_data = new(at) data::of< of_int   >::type( format, cast< type_of< of_int   >::type >( value ) );
            break;
        case of_float:
            m_data = new(at) data::of< of_float >::type( format, cast< type_of< of_float >::type >( value ) );
            break;
        case of_fixed:
            m_data = new(at) data::of< of_fixed >::type( format, cast< type_of< of_fixed >::type >( value ) );
            break;
        case of_text:
            m_data = new(at) data::of< of_text  >::type( format, cast< type_of< of_text  >::type >( value ) );
            break;
        default:
            unsupported_value_type<of_bool>( format.get_type(), format.get_name() );
            break;
        }
    }

    template<>
    field::field( void* at, field::format const& format, field::type_of< field::of_int >::type value )
    {
        switch( format.get_type() )
        {
        case of_int:
            m_data = new(at) data::of< of_int   >::type( format, value );
            break;
        case of_bool:
            m_data = new(at) data::of< of_bool  >::type( format, cast< type_of< of_bool  >::type >( value ) );
            break;
        case of_float:
            m_data = new(at) data::of< of_float >::type( format, cast< type_of< of_float >::type >( value ) );
            break;
        case of_fixed:
            m_data = new(at) data::of< of_fixed >::type( format, cast< type_of< of_fixed >::type >( value ) );
            break;
        case of_text:
            m_data = new(at) data::of< of_text  >::type( format, cast< type_of< of_text  >::type >( value ) );
            break;
        default:
            unsupported_value_type<of_int>( format.get_type(), format.get_name() );
            break;
        }
    }

    template<>
    field::field( void* at, field::format const& format, field::type_of< field::of_float >::type value )
    {
        switch( get_type() )
        {
        case of_float:
            m_data = new(at) data::of< of_float >::type( format, value );
            break;
        case of_bool:
            m_data = new(at) data::of< of_bool  >::type( format, cast< type_of< of_bool  >::type >( value ) );
            break;
        case of_int:
            m_data = new(at) data::of< of_int   >::type( format, cast< type_of< of_int   >::type >( value ) );
            break;
        case of_fixed:
            m_data = new(at) data::of< of_fixed >::type( format, cast< type_of< of_fixed >::type >( value ) );
            break;
        case of_text:
            m_data = new(at) data::of< of_text  >::type( format, cast< type_of< of_text  >::type >( value ) );
            break;
        default:
            unsupported_value_type<of_float>( format.get_type(), format.get_name() );
            break;
        }
    }

    template<>
    field::field( void* at, field::format const& format, text value )
    {
        switch( format.get_type() )
        {
        case of_text:
            m_data = new(at) data::of< of_text  >::type( format, value );
            break;
        case of_bool:
            m_data = new(at) data::of< of_bool  >::type( format, cast< type_of< of_bool  >::type >( value ) );
            break;
        case of_int:
            m_data = new(at) data::of< of_int   >::type( format, cast< type_of< of_int   >::type >( value ) );
            break;
        case of_float:
            m_data = new(at) data::of< of_float >::type( format, cast< type_of< of_float >::type >( value ) );
            break;
        case of_fixed:
            m_data = new(at) data::of< of_fixed >::type( format, cast< type_of< of_fixed >::type >( value ) );
            break;
        default:
            unsupported_value_type<of_text>( format.get_type(), format.get_name() );
            break;
        }
    }

    template<>
    bool field::get_value<bool>() const
    {
        switch( get_type() )
        {
        case of_bool:
            return static_cast< data::of< of_bool >::type* >( m_data )->get_value();
        default:
            return unsupported_value_type<of_bool>( get_type(), get_name() );
        }
    }

    template<>
    long long field::get_value<int64_t>() const
    {
        return static_cast< data::of< of_int >::type* >( m_data )->get_value();
    }

    template<>
    double field::get_value<double>() const
    {
        return static_cast< data::of< of_float >::type* >( m_data )->get_value();
    }

    template<>
    fixed field::get_value<fixed>() const
    {
        return static_cast< data::of< of_fixed >::type* >( m_data )->get_value();
    }

    template<>
    text field::get_value<text>() const
    {
        return static_cast< data::of< of_text >::type* >( m_data )->get_value();
    }

    template<>
    time field::get_value<time>() const
    {
        return static_cast< data::of< of_time >::type* >( m_data )->get_value();
    }

    template<>
    void field::set_value< field::type_of< field::of_bool >::type >( field::type_of< field::of_bool >::type val )
    {
        switch( get_type() )
        {
        case of_bool:
            static_cast< data::of< of_bool >::type* >( m_data )->set_value( val );
            break;
        default:
            unsupported_value_type<of_bool>( get_type(), get_name() );
            break;
        }
    }

    template<>
    void field::set_value< field::type_of< field::of_int >::type >( field::type_of< field::of_int >::type val )
    {
        switch( get_type() )
        {
        case of_int:
            static_cast< data::of< of_int >::type* >( m_data )->set_value( val );
            break;
        default:
            unsupported_value_type<of_int>( get_type(), get_name() );
            break;
        }
    }

    template<>
    void field::set_value< field::type_of< field::of_float >::type >( field::type_of< field::of_float >::type val )
    {
        switch( get_type() )
        {
        case of_float:
            static_cast< data::of< of_float >::type* >( m_data )->set_value( val );
            break;
        default:
            unsupported_value_type<of_float>( get_type(), get_name() );
            break;
        }
    }

    template<>
    void field::set_value< field::type_of< field::of_fixed >::type >( field::type_of< field::of_fixed >::type val )
    {
        switch( get_type() )
        {
        case of_fixed:
            static_cast< data::of< of_fixed >::type* >( m_data )->set_value( val );
            break;
        default:
            unsupported_value_type<of_fixed>( get_type(), get_name() );
            break;
        }
    }

    template<>
    void field::set_value< field::type_of< field::of_text >::type >( field::type_of< field::of_text >::type val )
    {
        switch( get_type() )
        {
        case of_text:
            static_cast< data::of< of_text >::type* >( m_data )->set_value( val );
            break;
        default:
            unsupported_value_type<of_text>( get_type(), get_name() );
            break;
        }
    }

//  field::format

    class field::format::data
    {
    public:
        data( text const& name, type t )
            : m_name(name), m_type(t) {
        }

        virtual ~data() {
        }

        text get_name() const {
            return m_name;
        }

        type get_type() const {
            return m_type;
        }

        virtual bool is_null_default() const = 0;

        virtual void clear_default() = 0;

        template< field::type T >
        struct of;

    private:
        text m_name;
        type m_type;
    };

    template< typename T >
    class field::format::value : public field::format::data
    {
    public:
        typedef data base;

        value( text const& name, field::type t )
            : base( name, t ), m_default() {
        }

        value( text const& name, field::type t, T val )
            : base( name, t ), m_default( val ) {
        }

        void assert_default_value_is_not_null()
        {
            if( !m_default )
                throw error( "Trying to retrieve default value which is NULL from format of field \"" + get_name() + '"', __FILE__, __LINE__ );
        }

        T get_default() {
            assert_default_value_is_not_null();
            return *m_default;
        }

        void set_default( T val ) {
            m_default = val;
        }

        bool is_null_default() const {
            return !m_default;
        }

        void clear_default() {
            m_default.set_null();
        }

    private:
        opt<T> m_default;
    };

    template< field::type T >
    struct field::format::data::of
    {
        typedef field::format::value< typename type_of<T>::type > type;
    };

    field::format::format( void* at, text const& name, type t )
    {
        switch( t )
        {
        case of_bool:
            m_data = new(at) data::of< of_bool  >::type( name, t );
            break;
        case of_int:
            m_data = new(at) data::of< of_int   >::type( name, t );
            break;
        case of_float:
            m_data = new(at) data::of< of_float >::type( name, t );
            break;
        case of_fixed:
            m_data = new(at) data::of< of_fixed >::type( name, t );
            break;
        case of_text:
            m_data = new(at) data::of< of_text  >::type( name, t );
            break;
        case of_time:
            m_data = new(at) data::of< of_time  >::type( name, t );
            break;
        default:
            invalid_field_type( *this );
            break;
        }
    }

    field::format::~format()
    {
        switch( get_type() )
        {
        case of_bool:
            static_cast< data::of< of_bool  >::type* >(m_data)->~value();
            break;
        case of_int:
            static_cast< data::of< of_int   >::type* >(m_data)->~value();
            break;
        case of_float:
            static_cast< data::of< of_float >::type* >(m_data)->~value();
            break;
        case of_fixed:
            static_cast< data::of< of_fixed >::type* >(m_data)->~value();
            break;
        case of_text:
            static_cast< data::of< of_text  >::type* >(m_data)->~value();
            break;
        case of_time:
            static_cast< data::of< of_time  >::type* >(m_data)->~value();
            break;
        default:
            break;
        }
    }

    text field::format::get_name() const
    {
        return m_data->get_name();
    }

    field::type field::format::get_type() const
    {
        return m_data->get_type();
    }

    bool field::format::is_null_default() const
    {
        return m_data->is_null_default();
    }

    void field::format::clear_default()
    {
        m_data->clear_default();
    }

    template<>
    field::format::format( void* at, text const& name, bool val )
    {
        m_data = new(at) data::of< of_bool >::type( name, of_bool, val );
    }

    template<>
    field::format::format( void* at, text const& name, long long val )
    {
        m_data = new(at) data::of< of_int >::type( name, of_int, val );
    }

    template<>
    field::format::format( void* at, text const& name, double val )
    {
        m_data = new(at) data::of< of_float >::type( name, of_float, val );
    }

    template<>
    field::format::format( void* at, text const& name, text val )
    {
        m_data = new(at) data::of< of_text >::type( name, of_text, val );
    }

    template< field::type T >
    typename field::type_of<T>::type invalid_retrieve_default_type( field::type t, text const& name )
    {
        throw error( "Invalid retrieve type " + field::type_text(T) + " to extract default value of type " 
                    + field::type_text(t) + " in format of field \"" + name + '"', __FILE__, __LINE__ );
    }

    template<>
    field::type_of< field::of_bool >::type field::format::get_default< field::type_of< field::of_bool >::type >() const
    {
        switch( get_type() )
        {
        case of_bool:
            return static_cast< data::of< of_bool >::type* >( m_data )->get_default();
        case of_int:
            return cast< type_of< of_bool >::type >( static_cast< data::of< of_int   >::type* >( m_data )->get_default() );
        case of_float:
            return cast< type_of< of_bool >::type >( static_cast< data::of< of_float >::type* >( m_data )->get_default() );
        case of_fixed:
            return cast< type_of< of_bool >::type >( static_cast< data::of< of_fixed >::type* >( m_data )->get_default() );
        case of_text:
            return cast< type_of< of_bool >::type >( static_cast< data::of< of_text  >::type* >( m_data )->get_default() );
        default:
            return invalid_retrieve_default_type<of_bool>( get_type(), get_name() );
        }
    }

    template<>
    field::type_of< field::of_int >::type field::format::get_default< field::type_of< field::of_int >::type >() const
    {
        switch( get_type() )
        {
        case of_int:
            return static_cast< data::of< of_int >::type* >( m_data )->get_default();
        case of_bool:
            return cast< type_of< of_int >::type >( static_cast< data::of< of_bool  >::type* >( m_data )->get_default() );
        case of_float:
            return cast< type_of< of_int >::type >( static_cast< data::of< of_float >::type* >( m_data )->get_default() );
        case of_fixed:
            return cast< type_of< of_int >::type >( static_cast< data::of< of_fixed >::type* >( m_data )->get_default() );
        case of_text:
            return cast< type_of< of_int >::type >( static_cast< data::of< of_text  >::type* >( m_data )->get_default() );
        default:
            return invalid_retrieve_default_type<of_int>( get_type(), get_name() );
        }
    }

    template<>
    field::type_of< field::of_float >::type field::format::get_default< field::type_of< field::of_float >::type >() const
    {
        switch( get_type() )
        {
        case of_float:
            return static_cast< data::of< of_float >::type* >( m_data )->get_default();
        case of_bool:
            return cast< type_of< of_float >::type >( static_cast< data::of< of_bool  >::type* >( m_data )->get_default() );
        case of_int:
            return cast< type_of< of_float >::type >( static_cast< data::of< of_int   >::type* >( m_data )->get_default() );
        case of_fixed:
            return cast< type_of< of_float >::type >( static_cast< data::of< of_fixed >::type* >( m_data )->get_default() );
        case of_text:
            return cast< type_of< of_float >::type >( static_cast< data::of< of_text  >::type* >( m_data )->get_default() );
        default:
            return invalid_retrieve_default_type<of_float>( get_type(), get_name() );
        }
    }

    template<>
    field::type_of< field::of_fixed >::type field::format::get_default< field::type_of< field::of_fixed >::type >() const
    {
        switch( get_type() )
        {
        case of_fixed:
            return static_cast< data::of< of_fixed >::type* >( m_data )->get_default();
        case of_bool:
            return cast< type_of< of_fixed >::type >( static_cast< data::of< of_bool  >::type* >( m_data )->get_default() );
        case of_int:
            return cast< type_of< of_fixed >::type >( static_cast< data::of< of_int   >::type* >( m_data )->get_default() );
        case of_float:
            return cast< type_of< of_fixed >::type >( static_cast< data::of< of_float >::type* >( m_data )->get_default() );
        case of_text:
            return cast< type_of< of_fixed >::type >( static_cast< data::of< of_text  >::type* >( m_data )->get_default() );
        default:
            return invalid_retrieve_default_type<of_fixed>( get_type(), get_name() );
        }
    }

    template<>
    field::type_of< field::of_text >::type field::format::get_default< field::type_of< field::of_text >::type >() const
    {
        switch( get_type() )
        {
        case of_text:
            return static_cast< data::of< of_text >::type* >( m_data )->get_default();
        case of_bool:
            return cast< type_of< of_text >::type >( static_cast< data::of< of_bool  >::type* >( m_data )->get_default() );
        case of_int:
            return cast< type_of< of_text >::type >( static_cast< data::of< of_int   >::type* >( m_data )->get_default() );
        case of_float:
            return cast< type_of< of_text >::type >( static_cast< data::of< of_float >::type* >( m_data )->get_default() );
        case of_fixed:
            return cast< type_of< of_text >::type >( static_cast< data::of< of_fixed >::type* >( m_data )->get_default() );
        default:
            return invalid_retrieve_default_type<of_text>( get_type(), get_name() );
        }
    }

    template<>
    field::type_of< field::of_time >::type field::format::get_default< field::type_of< field::of_time >::type >() const
    {
        switch( get_type() )
        {
        case of_time:
            return static_cast< data::of< of_time >::type* >( m_data )->get_default();
        case of_text:
            return cast< field::type_of< of_time >::type >( static_cast< data::of< of_text >::type* >( m_data )->get_default() );
        default:
            return invalid_retrieve_default_type<of_time>( get_type(), get_name() );
        }
    }

    template<>
    void field::format::set_default< field::type_of< field::of_bool >::type >( field::type_of< field::of_bool >::type value )
    {
        switch( get_type() )
        {
        case of_bool:
            static_cast< data::of< of_bool  >::type* >( m_data )->set_default( value );
            break;
        case of_int:
            static_cast< data::of< of_int   >::type* >( m_data )->set_default( cast< field::type_of< of_int   >::type >( value ) );
            break;
        case of_float:
            static_cast< data::of< of_float >::type* >( m_data )->set_default( cast< field::type_of< of_float >::type >( value ) );
            break;
        case of_fixed:
            static_cast< data::of< of_fixed >::type* >( m_data )->set_default( cast< field::type_of< of_fixed >::type >( value ) );
            break;
        case of_text:
            static_cast< data::of< of_text  >::type* >( m_data )->set_default( cast< field::type_of< of_text  >::type >( value ) );
            break;
        default:
            invalid_retrieve_default_type< of_bool >( get_type(), get_name() );
            break;
        }
    }

    template<>
    void field::format::set_default< field::type_of< field::of_int >::type >( field::type_of< field::of_int >::type value )
    {
        switch( get_type() )
        {
        case of_int:
            static_cast< data::of< of_int   >::type* >( m_data )->set_default( value );
            break;
        case of_bool:
            static_cast< data::of< of_bool  >::type* >( m_data )->set_default( cast< field::type_of< field::of_bool  >::type >( value ) );
            break;
        case of_float:
            static_cast< data::of< of_float >::type* >( m_data )->set_default( cast< field::type_of< field::of_float >::type >( value ) );
            break;
        case of_fixed:
            static_cast< data::of< of_fixed >::type* >( m_data )->set_default( cast< field::type_of< field::of_fixed >::type >( value ) );
            break;
        case of_text:
            static_cast< data::of< of_text  >::type* >( m_data )->set_default( cast< field::type_of< field::of_text  >::type >( value ) );
            break;
        default:
            invalid_retrieve_default_type< of_int >( get_type(), get_name() );
            break;
        }
    }

    template<>
    void field::format::set_default< field::type_of< field::of_float >::type >( field::type_of< field::of_float >::type value )
    {
        switch( get_type() )
        {
        case of_float:
            static_cast< data::of< of_float >::type* >( m_data )->set_default( value );
            break;
        case of_bool:
            static_cast< data::of< of_bool  >::type* >( m_data )->set_default( cast< field::type_of< field::of_bool  >::type >( value ) );
            break;
        case of_int:
            static_cast< data::of< of_int   >::type* >( m_data )->set_default( cast< field::type_of< field::of_int   >::type >( value ) );
            break;
        case of_fixed:
            static_cast< data::of< of_fixed >::type* >( m_data )->set_default( cast< field::type_of< field::of_fixed >::type >( value ) );
            break;
        case of_text:
            static_cast< data::of< of_text  >::type* >( m_data )->set_default( cast< field::type_of< field::of_text  >::type >( value ) );
            break;
        default:
            invalid_retrieve_default_type<of_float>( get_type(), get_name() );
            break;
        }
    }

    template<>
    void field::format::set_default< field::type_of< field::of_text >::type >( field::type_of< field::of_text >::type value )
    {
        switch( get_type() )
        {
        case of_text:
            static_cast< data::of< of_text >::type* >( m_data )->set_default( value );
            break;
        case of_bool:
            static_cast< data::of< of_bool  >::type* >( m_data )->set_default( cast< field::type_of< field::of_bool  >::type >( value ) );
            break;
        case of_int:
            static_cast< data::of< of_int   >::type* >( m_data )->set_default( cast< field::type_of< field::of_int   >::type >( value ) );
            break;
        case of_float:
            static_cast< data::of< of_float >::type* >( m_data )->set_default( cast< field::type_of< field::of_float >::type >( value ) );
            break;
        case of_fixed:
            static_cast< data::of< of_fixed >::type* >( m_data )->set_default( cast< field::type_of< field::of_fixed >::type >( value ) );
            break;
        case of_time:
            static_cast< data::of< of_time  >::type* >( m_data )->set_default( cast< field::type_of< field::of_time  >::type >( value ) );
            break;
        default:
            invalid_retrieve_default_type<of_text>( get_type(), get_name() );
            break;
        }
    }

    template<>
    void field::format::set_default< field::type_of< field::of_time >::type >( field::type_of< field::of_time >::type value )
    {
        switch( get_type() )
        {
        case of_time:
            static_cast< data::of< of_time >::type* >( m_data )->set_default( value );
            break;
        case of_text:
            static_cast< data::of< of_text >::type* >( m_data )->set_default( cast< field::type_of< field::of_text >::type >( value ) );
            break;
        default:
            invalid_retrieve_default_type<of_time>( get_type(), get_name() );
            break;
        }
    }

    void throw_value_invalid_type( const char* type_name )
    {
        throw error( "Invalid field value type " + text(type_name), __FILE__, __LINE__ );
    }
}
